import 'dart:convert';
import 'dart:math';

import 'package:flutter_screenutil/flutter_screenutil.dart';

enum DateType {
  year,
  month,
  day,
}

extension YMap on Map {
  Map<String, dynamic> transfer() {
    return this.map((k, v) => MapEntry(k.toString(), v));
  }
}

extension TruncateDouble on double {
  double truncateTo(int decimalPlaces) {
    final factor = pow(10, decimalPlaces).toDouble();
    return (this * factor).truncateToDouble() / factor;
  }
}

extension DoubleExtension on double {
  double get yw => ScreenUtil().setWidth(this);

  double get yh => ScreenUtil().setHeight(this);

  double get ysp => ScreenUtil().setSp(this);
}

bool isInteger(String str) {
  if (str.isEmpty) return false;
  return RegExp(r'^-?\d+$').hasMatch(str);
}

bool isJson(value) {
  if (value is String) {
    try {
      jsonDecode(value);
      return true;
    } catch (e) {
      return false;
    }
  } else {
    return false;
  }
}

extension StringExtension on String {
  bool isYJson() {
    try {
      json.decode(this);
      return true;
    } catch (e) {
      return false;
    }
  }

  String map(Map<String, dynamic> map, {String? key}) {
    return yToString(map[key ?? this]);
  }

  List<T> toListModel<T>(Map<String, dynamic> map, {String? key, onModel}) {
    return yToListModel<T>(map[key ?? this], onModel: onModel);
  }

  T toModel<T>(Map<String, dynamic> map, {String? key, onModel}) {
    return onModel((map[key ?? this] ?? {}));
  }

  ///根据出生日期计算多少岁
  String calculateDetailedAge({DateType type = DateType.year}) {
    final now = DateTime.now();
    DateTime birthDate = DateTime.parse(this);

    int years = now.year - birthDate.year;
    int months = now.month - birthDate.month;
    int days = now.day - birthDate.day;

    if (days < 0) {
      months--;
      days += DateTime(now.year, now.month, 0).day;
    }

    if (months < 0) {
      years--;
      months += 12;
    }
    if (type == DateType.year) {
      return years.toString();
    } else if (type == DateType.month) {
      return '$years 岁 $months 个月';
    }
    return '$years 岁 $months 个月 $days 天';
  }
}

extension IntExtension on int {
  int map(Map<String, dynamic> map, {String? key}) {
    return yToInt(map[key ?? this.toString()]);
  }
}

int yToInt(dynamic value) {
  if (value is String) {
    if (value.isEmpty) {
      return 0;
    } else {
      return int.parse(value.toString());
    }
  } else if (value is double) {
    return value.toInt();
  } else if (value is int) {
    return value;
  } else {
    return 0;
  }
}

String yToString(dynamic value, {int position = 2, bool showLine = true}) {
  if (value == null && showLine) {
    return '--';
  }
  if (value == null && !showLine) {
    return '';
  }
  if (value is String) {
    return (value.isEmpty && showLine) ? '--' : value;
  } else if (value is int) {
    return value.toString();
  } else if (value is double) {
    return value.truncateTo(position).toString();
  } else {
    return value.toString();
  }
}

double yToDouble(dynamic value, {int position = 2}) {
  if (value == null) {
    return 0;
  }
  if (value is double) {
    return value.truncateTo(position);
  } else if (value is int) {
    return value.toDouble();
  } else if (value is String) {
    return double.parse(value).truncateTo(2);
  } else {
    return 0;
  }
}

List<T> yToListModel<T>(data, {onModel}) {
  if (onModel != null) {
    if (data is Map) {
      return [onModel(data)];
    } else if (data is List) {
      List<T> v = [];
      for (var e in data) {
        v.add(onModel(e));
      }
      return v;
    }
  } else {
    return data ?? [];
  }
  return [];
}
